package com.jd.platform.gobrs.client.core.key;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.thread.NamedThreadFactory;
import com.alibaba.fastjson.JSON;
import com.ibm.etcd.api.KeyValue;
import com.jd.platform.gobrs.client.ApplicationContextProvider;
import com.jd.platform.gobrs.client.Context;
import com.jd.platform.gobrs.client.enable.AutoDepBean;
import com.jd.platform.gobrs.client.enable.ManualDepBean;
import com.jd.platform.gobrs.client.etcd.EtcdConfig;
import com.jd.platform.gobrs.client.server.ServerQuery;
import com.jd.platform.gobrs.common.configcenter.ConfigConstant;
import com.jd.platform.gobrs.common.configcenter.IConfigCenter;
import com.jd.platform.gobrs.common.model.GCacheKeyModel;
import com.jd.platform.gobrs.common.model.KeyCountModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 定时推送一批key到worker
 *
 * @author sizegang wrote on 2020-01-06
 * @version 1.0
 */
@Slf4j
public class PushSchedulerStarter {

    @Autowired
    private ApplicationContextProvider applicationContextProvider;

    @Value("${server.port}")
    private Integer port;

    /**
     * 每0.5秒推送一次待测key
     */
    public void startPusher(Long period) {
        boolean autoEnabled = false;
        boolean manualEnabled = false;
        try {
            autoEnabled = checkEnabled(AutoDepBean.AutoMarker.class);
            manualEnabled = checkEnabled(ManualDepBean.ManualMarker.class);
        } catch (Exception ex) {
//            log.warn("PushSchedulerStarter start warning {}", ex);
        }
        if (period == null || period <= 0) {
            period = 500L;
        }
//        if (autoEnabled) {
//            @SuppressWarnings("PMD.ThreadPoolCreationRule")
//            ScheduledExecutorService autoScheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("gobrs-autokey-service-executor", true));
//            autoScheduler.scheduleAtFixedRate(() -> {
//                doStartPusher(KeyHandlerFactory.getAutoCollector(), KeyHandlerFactory.getPusher());
//            }, 0, period, TimeUnit.MILLISECONDS);
//        }

        if (manualEnabled) {
            ScheduledExecutorService manualExecutorService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("gobrs-manualkey-pusher-service-executor", true));
            manualExecutorService.scheduleAtFixedRate(() -> {
                doStartPusher(KeyHandlerFactory.getCollector(), KeyHandlerFactory.getPusher());
            }, 0, period, TimeUnit.MILLISECONDS);
        }

    }

    private void doStartPusher(IKeyCollector iKeyCollector, IKeyPusher iKeyPusher) {
        // 获取待推送的热点key 从 收集器 中获取
        List<GCacheKeyModel> hotKeyModels = iKeyCollector.lockAndGetResult();
        if (CollectionUtil.isNotEmpty(hotKeyModels)) {
            // 从工厂中获取 推送器 开始将热点key推送给 server
            iKeyPusher.send(Context.APP_NAME, hotKeyModels);
            iKeyCollector.finishOnce();
        }
    }


    /**
     * 每10秒推送一次数量统计
     */

    public void startCountPusher(Integer period) {

        if (period == null || period <= 0) {
            period = 10;
        }
        boolean autoEnabled = false;
        boolean manualEnabled = false;
        try {
            autoEnabled = checkEnabled(AutoDepBean.AutoMarker.class);
            manualEnabled = checkEnabled(ManualDepBean.ManualMarker.class);
        } catch (Exception ex) {
//            log.warn("startCountPusher warning {}", ex);
        }
        @SuppressWarnings("PMD.ThreadPoolCreationRule")
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("gobrs-count-pusher-service-executor", true));
        boolean finalManualEnabled = manualEnabled;
        scheduledExecutorService.scheduleAtFixedRate(() -> {
//            if (autoEnabled) {
//                doStartCountPusher(KeyHandlerFactory.getAutoCounter(), KeyHandlerFactory.getPusher());
//            }
            if (finalManualEnabled) {
                doStartCountPusher(KeyHandlerFactory.getCounter(), KeyHandlerFactory.getPusher());
            }
        }, 0, period, TimeUnit.SECONDS);
    }

    private void doStartCountPusher(IKeyCollector iKeyCollector, IKeyPusher iKeyPusher) {
        List<KeyCountModel> keyCountModels = iKeyCollector.lockAndGetResult();
        if (CollectionUtil.isNotEmpty(keyCountModels)) {
            iKeyPusher.sendCount(Context.APP_NAME, keyCountModels);
            iKeyCollector.finishOnce();
        }
    }


    public void schdulerLoad(Long period) {
        startPusher(period);
        startCountPusher(10);
        boolean autoEnabled = false;
        try {
            autoEnabled = checkEnabled(AutoDepBean.AutoMarker.class);
        } catch (Exception ex) {
        }
        if (autoEnabled) {
            startInfoPusher(10);
        }

    }

    /**
     * 上报信息到etcd
     *
     * @param time
     */
    private void startInfoPusher(int time) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            ServerQuery server = new ServerQuery();
            try {
                server.copyTo();
            } catch (Exception e) {
                e.printStackTrace();
            }
            IConfigCenter iConfigCenter = EtcdConfig.configCenter();
            String key = ConfigConstant.hotKeyPath + Context.APP_NAME + "/" + server.getSys().getComputerIp() + "/" + port;
            iConfigCenter.put(key, JSON.toJSONString(server));
        }, 2, time, TimeUnit.SECONDS);
    }

    private boolean checkEnabled(Class clazz) {
        Object bean = applicationContextProvider.getBean(clazz);
        if (bean == null) {
            return false;
        }
        return true;
    }

}
